Security, bugs, SEO, performance, responsive layout and UK legal/compliance review of "CyberSight Website.html". Technical issues have been fixed in the live file; items needing a business decision or pre-launch action are flagged.
| Item | Finding | Status |
|---|---|---|
| XSS surface | No innerHTML/eval sinks; search and status messages use textContent; no URL-parameter parsing. Static page, no injection path found. | PASS |
| Third-party scripts | React/ReactDOM/Babel pinned to exact versions with SRI integrity hashes + crossorigin. Google Fonts CSS can't carry SRI (dynamic) — acceptable, but self-host fonts at launch for zero third-party dependency. | PASS |
| Referrer leakage | No referrer policy was set. Added strict-origin-when-cross-origin meta. | FIXED |
| Form data | Mock form — nothing is transmitted or stored; no PII risk today. When a backend is added: HTTPS-only POST, server-side validation, CSRF token, rate limiting and spam protection are required, plus encrypted storage if enquiries are retained. | PRE-LAUNCH |
| Security headers | CSP, HSTS, X-Content-Type-Options, X-Frame-Options/frame-ancestors, Permissions-Policy must be set at the server/CDN level on the production host — they cannot be reliably set from HTML. Recommended baseline documented below. | PRE-LAUNCH |
| localStorage use | Only stores theme + language preference strings; wrapped in try/catch; no sensitive data. | PASS |
| External links | No target="_blank" links yet, so no rel="noopener" exposure. Apply rel="noopener noreferrer" when social URLs go live. | NOTE |
| Item | Finding | Status |
|---|---|---|
| Dark-mode flash (FOUC) | Saved dark theme was applied at the END of the page, so dark-mode users saw a light flash on every load. Theme class is now applied by a tiny script before first paint. | FIXED |
| iOS input zoom | Form fields were 15px — iOS Safari auto-zooms inputs under 16px, breaking layout on focus. Raised to 16px. | FIXED |
| Layout shift (CLS) | Logo images had no intrinsic dimensions. Added width/height attributes; footer mark lazy-loads. | FIXED |
| Reveal fail-safe | Previously hardened: content cannot stay hidden if IntersectionObserver is missing/inert; reduced-motion users get no animation. | PASS |
| Content consistency — emergency response | Emergency triage is now registered-clients-only, but four places still read as public: the stats strip ("4 hrs emergency response", "24/7 availability"), process step 01 ("4 hours for emergencies"), the contact line ("for urgent incidents, call us — any hour") and FAQ answers 1 & 5. Needs your wording call — flagged previously. | DECISION |
| Search coverage | Site search hides on mobile (<720px) and isn't replicated in the mobile menu — acceptable for a one-pager; add it to the menu if mobile analytics show demand. | NOTE |
| Item | Finding | Status |
|---|---|---|
| Meta description | Missing — added a 156-character description targeting "digital forensics UK public sector". | FIXED |
| Canonical + robots | Missing — added rel="canonical" (placeholder domain) and robots: index, follow. | FIXED |
| Social previews | No Open Graph / Twitter Card tags — added. og:image points to /og-image.png: a 1200×630 share image needs creating at launch (I can produce one from the brand). | FIXED |
| Structured data | Added JSON-LD ProfessionalService (name, legal name, contact, area served). Extend with address + sameAs (social URLs) when known. | FIXED |
| Favicon / theme-color | Missing — added (brand badge mark + ink theme-color). | FIXED |
| Semantics | Single h1, logical h2/h3 hierarchy, landmark elements, descriptive link text — already strong. | PASS |
| Bilingual SEO | When Welsh content exists, serve it at a real URL (e.g. /cy/) with hreflang pairs — the current client-side picker is invisible to crawlers. | PRE-LAUNCH |
| Item | Finding | Status |
|---|---|---|
| Hero asset weight | The evidence card loaded a 1024×1024 PNG (~40KB) to display at 16px. Swapped to the 1KB SVG mark. | FIXED |
| Tweaks tooling | React + ReactDOM + Babel (~1.6MB dev builds) load solely for the design-review Tweaks panel. Fine during design; strip all four script tags + #tweaks-root for production — the site itself is plain HTML/CSS/JS and doesn't need them. | PRE-LAUNCH |
| CSS delivery | Single inline stylesheet — zero render-blocking requests. Good for a one-pager. | PASS |
| Fonts | 3 families via Google Fonts with preconnect + display=swap. At launch, self-host WOFF2 subsets (saves ~2 round trips, removes third party). | NOTE |
| Scripts | Site JS is ~3KB, runs at end of body, no long tasks. Scroll handler uses IntersectionObserver (no scroll-event jank). | PASS |
| Item | Finding | Status |
|---|---|---|
| Breakpoints | 1080px (hamburger), 900px (single-column hero/about/contact, 2-col grids), 720px (compact nav), 600px (single-col grids, 2×2 stats) — verified no horizontal overflow at 375/768/1280. | PASS |
| Navigation | Accessible hamburger menu with 44px+ targets; CTA moves into the menu on small screens. | PASS |
| Touch targets | All interactive elements ≥44px (AAA) after the accessibility pass. | PASS |
| iOS zoom / viewport | 16px inputs (fixed above); viewport meta correct; pinch-zoom not disabled. | FIXED |
| Clickable contact details | Email and phone were plain text — now mailto: and tel: links (one-tap on mobile). | FIXED |
| Item | Finding | Status |
|---|---|---|
| Certification badges | Risk: the footer displays ISO 9001 / ISO 27001 / Cyber Essentials Plus as badges while the compliance section says these are "in progress". Displaying certifications not yet held risks breaching ASA/CMA misleading-claims rules, and the Cyber Essentials mark is licence-restricted to certified organisations. Options: (a) remove until certified, (b) relabel the strip "Working towards", or (c) keep only what is actually held. | DECISION |
| Companies Act 2006 s.82 | Company name, number and registered office placeholders are present in the footer — must be real values before the site is public. | PRE-LAUNCH |
| UK GDPR / ICO | Form carries a data-protection notice and "no case-sensitive data" warning; ICO registration number is a placeholder. Privacy Policy page must exist and be linked before collecting any real enquiry data. | PRE-LAUNCH |
| PECR / cookies | No cookies, no analytics, no tracking. localStorage holds only user-requested preferences (theme/language), which sits in the "strictly necessary/preference" category — document it in the Cookie Policy. If analytics are added later, a consent banner becomes required. | PASS |
| Government affiliation | Non-affiliation disclaimer present in the footer; no crowns, crests or "gov" styling used — consistent with the naming research guidance. | PASS |
| Statutory policy pages | Privacy, Cookie, Terms, Accessibility and Modern Slavery links are placeholders ("#"). Note: a Modern Slavery statement is only mandatory above £36M turnover — keeping it voluntarily is good practice for public-sector procurement. I can draft all five pages. | PRE-LAUNCH |
| Claims accuracy | "100% documented chain of custody" and response-time figures are service commitments — ensure SLAs can substantiate them before launch (ASA substantiation rules). | PRE-LAUNCH |
Content-Security-Policy | default-src 'self'; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src fonts.gstatic.com; img-src 'self'; script-src 'self' (tighten further once fonts are self-hosted and inline JS is externalised) |
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload |
X-Content-Type-Options | nosniff |
X-Frame-Options | DENY (or CSP frame-ancestors 'none') |
Permissions-Policy | camera=(), microphone=(), geolocation=() |
Method: full manual code review of the production file, plus live verification of layout at 375/768/1280px and both themes. Advisory only — commission penetration testing and a legal review before public launch. Companion report: "CyberSight WCAG Audit.html" (accessibility, AA met / 10 of 12 AAA).